"""
进程间通信-Queue、Pipe、Manager

核心知识点：
    1.需要使用多进程的Queue而不能使用多线程的Queue
    2.共享全局变量不能适用于多进程编程，可以适用于多线程编程
    3.multiprocessing中的Queue不能用于pool进程池
    4.pool进程池中的进程间通信需要使用Manager中的Queue
    5.pipe只能适用于两个进程，pipe性能高于Queue（Queue进程间通信加了锁）
"""

import time
from multiprocessing import Process, Queue, Manager, Pool, Pipe


def producer(queue):
    queue.put("apple")
    time.sleep(2)


def consumer(queue):
    time.sleep(2)
    data = queue.get()
    print(data)


def use_process():
    # 需要使用多进程的Queue而不能使用多线程的Queue
    queue = Queue()
    my_producer = Process(target=producer, args=(queue,))
    my_consumer = Process(target=consumer, args=(queue,))
    my_producer.start()
    my_consumer.start()
    my_producer.join()
    my_consumer.join()
    # 输出结果：
    """
    apple
    """


def use_process_pool():
    # pool中的进程间通信需要使用Manager中的Queue
    queue = Manager().Queue()
    pool = Pool(2)
    pool.apply_async(producer, args=(queue,))
    pool.apply_async(consumer, args=(queue,))

    pool.close()
    pool.join()
    # 输出结果：
    """
    apple
    """


def producer_pipe(pipe):
    pipe.send("apple")
    time.sleep(2)


def consumer_pipe(pipe):
    time.sleep(2)
    data = pipe.recv()
    print(data)


def use_process_pipe():
    # pipe只能适用于两个进程
    recevie_pipe, send_pipe = Pipe()

    my_producer = Process(target=producer_pipe, args=(send_pipe,))
    my_consumer = Process(target=consumer_pipe, args=(recevie_pipe,))

    my_producer.start()
    my_consumer.start()
    my_producer.join()
    my_consumer.join()
    # 输出结果：
    """
    apple
    """


def add_data(p_dict, key, value):
    p_dict[key] = value


def use_process_dict():
    """
    Manager提供的共享内存（需要注意数据同步的问题）
    """
    p_dict = Manager().dict()

    first_process = Process(target=add_data, args=(p_dict, "google", "GOOG"))
    second_process = Process(target=add_data, args=(p_dict, "apple", "APPL"))

    first_process.start()
    second_process.start()
    first_process.join()
    second_process.join()
    print(p_dict)
    # 输出结果：
    """
    {'apple': 'APPL', 'google': 'GOOG'}
    """


if __name__ == '__main__':
    # use_process()
    # use_process_pool()
    # use_process_pipe()
    use_process_dict()
